#ifndef __TILT_PROCESS_H__
#define __TILT_PROCESS_H__

#include <math.h>

#define KTiltGainFactor 5

template <class T>
class TiltProcess
{

public:
	TiltProcess() { freq = 1000; gain = 0; bypass = false; amp = 6/log(2.0f); calcFilter(); }
	TiltProcess(double f, double g) { freq = f; gain = g; bypass = false; amp = 6/log(2.0f); calcFilter(); }

	void process(double inLeft, double inRight, double *outLeft, double *outRight)
	{
		if(bypass)
		{
			*outLeft = inLeft;
			*outRight = inRight;
		}
		else
		{
			lp_out_L = a0 * inLeft + b1 * lp_out_L;
			lp_out_R = a0 * inRight + b1 * lp_out_R;

			*outLeft = inLeft + lgain * lp_out_L + hgain * (inLeft - lp_out_L);
			*outRight = inRight + lgain * lp_out_R + hgain * (inRight - lp_out_R);
		}
	}

	void setBypass(bool b) { bypass = b; }
	bool getBypass() { return bypass; }

	void setFreq(double f) { freq = f; calcFilter(); }
	double getFreq() { return freq; }
	
	void setGain(double g) { 
		double g1, g2;
		gain = g;

		if (gain > 0) {
			g1 = -KTiltGainFactor * gain;
			g2 = gain;
		} else {
			g1 = -gain;
			g2 = KTiltGainFactor * gain;
		}

		//two separate gains
		lgain = exp(g1/amp)-1;
		hgain = exp(g2/amp)-1;
	}
	double getGain() { return gain; }

	void setSampleRate(double sr) { sRate = sr; calcFilter(); }

private:
	void calcFilter() {
		double sr3 = sRate * 3;
		double omega = 2 * M_PI * freq;
		double n = 1/(sr3 + omega);
		a0 = 2 * omega * n;
		b1 = (sr3 - omega) * n;
	}

	double sRate;
	double gain, freq, amp;
	double lp_out_L, lp_out_R;
	double lgain, hgain;
	double a0, b1;
	bool bypass;
};

#endif //  __TILT_PROCESS_H__